#include "uart.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"
#include "utils/byte_queue.h"
#include "bsp/board_config.h"

#define TX_CACHE_SIZE CONFIG_UART_TX_SIZE
#define RX_CACHE_SIZE CONFIG_UART_RX_SIZE

u8 tx_cache[TX_CACHE_SIZE];
u8 rx_cache[RX_CACHE_SIZE];
byte_queue_t uart_tx_queue;
byte_queue_t uart_rx_queue;
static bool _b_inited = false;
void uart_init() {
	if (_b_inited) {
		return;
	}
	_b_inited = true;
    byte_queue_init(&uart_tx_queue, tx_cache, TX_CACHE_SIZE);
	byte_queue_init(&uart_rx_queue, rx_cache, RX_CACHE_SIZE);
	MX_USB_DEVICE_Init();
}

void uart_deinit(void) {
	if (!_b_inited) {
		return;
	}
	_b_inited = false;
	MX_USB_DEVICE_DeInit();
}

void uart_tx_poll(void) {
	u8 buffer[32];
	while(true) {
		if (CDC_Transmit_isBusy() == USBD_BUSY) {
			break;
		}
		u16 len = byte_queue_read(&uart_tx_queue, buffer, sizeof(buffer));
		if (len <= 0) {
			break;
		}
		CDC_Transmit_FS(buffer, len);
	}
}

void uart_rx_poll(void) {
	u8 buffer[64];
	while(true) {
		u16 len = byte_queue_read(&uart_rx_queue, buffer, sizeof(buffer));
		if (len <= 0) {
			break;
		}
		serial_on_data_received(buffer, len);
	}
}

void usb_uart_rx_handler(u8 *data, u32 len) {
	byte_queue_write(&uart_rx_queue, data, len);
}
